/*
 * =====================================================================================
 *
 *       Filename:  inmServer.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  08/10/2012 04:11:04 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  wangtengchao , wangtengchao AT gmail.com
 *   Organization:  
 *
 * =====================================================================================
 */
#include "inmServer.h"
#include "netBuffer.h"
#include "tcpConnect.h"
#include<iostream>
#include<boost/bind.hpp>
using namespace inm::net;
InmServer::InmServer(const InetAddr &serverAddr, int threadNum)
    :tcpServer_(serverAddr,"InmServer",threadNum)
{
	//attention! bind messageCodecCallback not messageCallback
    tcpServer_.setMessageCallback(boost::bind(&InmServer::messageCodecCallback,this,_1,_2,_3));
}

void InmServer::messageCallback(const TcpConnectPtr &t, const std::string &msg, const Timestamp &time)
{
#ifdef NET_DEBUG
	std::cout<<"messageCallback"<<std::endl;
#endif

    sendMessage(t,msg);
}

void InmServer::messageCodecCallback(const TcpConnectPtr &t, NetBuffer *buf, const Timestamp &time)
{//codec serveral small messages to a total message
    //readable() >= headerLen    headerLen = 4
#ifdef NET_DEBUG
	std::cout<<"codec"<<std::endl;
#endif
    while(buf->readableNum() >= headerLen)
    {//must use while because it may have serveral messages in buffer
        const void* data = buf->peek();
        uint32_t len = ntohl(*(reinterpret_cast<const uint32_t*>(data)));
        if(buf->readableNum() >= headerLen + len)
        {//a total message
            Timestamp time = Timestamp::now();
            buf->retrive(headerLen);
            messageCallback(t,buf->readAndRetrive(len),time);
        }
        else
            break;
    }
}
void InmServer::sendMessage(const TcpConnectPtr &tcpConn, const std::string &msg)
{//prepend the size of message
    NetBuffer buffer;
    buffer.append(msg.data(),msg.size());
    uint32_t size = htonl(msg.size());
    buffer.prepend(&size,sizeof(size));
#ifdef NET_DEBUG
	std::cout<<"send message length(include header)"<<buffer.readableNum()<<std::endl;
#endif
    tcpConn->sendMessage(buffer);
}

void InmServer::run()
{
    tcpServer_.run();
}
void InmServer::quit()
{
	tcpServer_.quit();
}
